function [result, headers, status] = http_query(server, url, variables)
% http_query  - perform a HTTP request with ?var1=...;var=2...
%
% http_query passes the query to http_get after the variables have
% been appended to the URL
%
% FORMAT:       [result, headers, status] = http_query([srv,] url, vars)
%
% Input fields:
%
%       srv         can either be a named server or an IP address,
%                   with or without a preceding 'http://', and a
%                   possible port specification after a colon
%       url         if server is given, the file/partial URL on
%                   the server, otherwise the complete URL (also
%                   with or without the preceding 'http://'
%       vars        either a 1xN cell array (only char arguments)
%                   with alternating name and content cells or a
%                   1x1 struct with one variable stored per field
%
% Output fields:
%
%       result      the response of the HTTP server with the headers
%                   already stripped
%       headers     the returned headers of the HTTP server
%       status      the returned HTTP status code (e.g. 200)
%
% NOTE:         The most crucial checks for special characters in
%               variable content (<,=,>,&,+,;) is made to prevent
%               bad requests
%
% See also http_get.

% Version:  v0.7f
% Build:    8110521
% Date:     Nov-05 2008, 9:00 PM CET
% Author:   Jochen Weber, SCAN Unit, Columbia University, NYC, NY, USA
% URL/Info: http://wiki.brainvoyager.com/BVQXtools

% argument check
if nargin < 2
    error( ...
        'BVQXtools:TooFewArguments',...
        'Too few arguments. Try ''help %s''.',...
        mfilename ...
    );
end

% for two arguments, URL is in first argument!
if nargin == 2
    variables = url;
    url = server;
else
    url = strrep([server '/' url],'//','/');
end
getvars = '?';

% check variables
if ~isstruct(variables) && ...
   ~iscell(variables)
    error( ...
        'BVQXtools:BadArgument',...
        'Bad variables argument.' ...
    );
end

% check struct type
if isstruct(variables)
    vf = fieldnames(variables);
    for fc=1:numel(vf)
        try
            getvars = i_addvar(getvars, vf{fc}, variables(1).(vf{fc}));
        catch
            % nothing
        end
    end

% check cell type
else
    for fc=2:2:numel(variables)
        try
            getvars = i_addvar(getvars,variables{fc-1},variables{fc});
        catch
            % nothing
        end
    end
end
getvars(end) = [];

% display and make call
disp([url getvars]);
[result, headers, status] = http_get([url getvars]);



% internal function
function gvs = i_addvar(gvs,vn,vc)
    rchars = find(vc<46 | vc==58 | (vc>59&vc<63) | ...
        (vc>90&vc<95) | vc==96 | (vc>122&vc<126) | vc>126);
    if ~isempty(rchars)
        vc = cellstr(vc');
        for rc = rchars
            vc{rc} = sprintf('%%%02X', double(vc{rc}));
        end
        vc = gluetostring(vc','');
    end
    gvs = [gvs vn '=' vc ';'];
return;
